package com.vip.workflow.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.vip.common.response.ErrorCode;
import com.vip.common.response.Result;
import com.vip.common.response.Results;
import com.vip.workflow.constant.UrlConsts;
import com.vip.workflow.service.IModelService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Model;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * 模板管理 Service实现类
 *
 * @author wgb
 * @date 2020/5/7 11:27
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ModelServiceImpl implements IModelService {
    private final RepositoryService repositoryService;
    private final ObjectMapper objectMapper;

    @Override
    public Result<List<Model>> getModelList(Integer pageNo, Integer pageSize) {
        try {
            List<Model> list = repositoryService.createModelQuery().listPage((pageNo - 1) * pageSize, pageSize);
            int total = (int) repositoryService.createModelQuery().count();
            return Results.newSuccessResult(list, "查询成功", total);
        } catch (Exception e) {
            log.error("获取模板列表出错", e);
        }
        return Results.newFailResult(ErrorCode.SYSTEM_ERROR, "查询失败");
    }

    @Override
    public void addNewModel(HttpServletResponse response) {
        try {
            //初始化一个空模型
            Model model = repositoryService.newModel();
            //设置一些默认信息
            String name = "new-process";
            String description = "";
            int revision = 1;
            String key = "process";
            ObjectNode modelNode = objectMapper.createObjectNode();
            modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);
            modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
            modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);
            model.setName(name);
            model.setKey(key);
            model.setMetaInfo(modelNode.toString());
            // 保存模板
            repositoryService.saveModel(model);
            String id = model.getId();
            //完善ModelEditorSource
            ObjectNode editorNode = objectMapper.createObjectNode();
            editorNode.put("id", "canvas");
            editorNode.put("resourceId", "canvas");
            ObjectNode stencilSetNode = objectMapper.createObjectNode();
            stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
            editorNode.put("stencilset", stencilSetNode);
            repositoryService.addModelEditorSource(id, editorNode.toString().getBytes(StandardCharsets.UTF_8));
            response.sendRedirect(String.format("%s/modeler?modelId=%s", UrlConsts.WORK_FLOW_CODE, id));
            log.info("创建模板完善ModelEditorSource结束");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public Result<String> removeModelById(String id) {
        try {
            repositoryService.deleteModel(id);
            return Results.newSuccessResult(null, "删除成功");
        } catch (Exception e) {
            log.error("删除指定模板出错", e);
        }
        return Results.newFailResult(ErrorCode.SYSTEM_ERROR, "删除失败");
    }

    @Override
    public Result<String> removeMultiModel(List<String> ids) {
        try {
            for (String id : ids) {
                repositoryService.deleteModel(id);
            }
            return Results.newSuccessResult(null, "删除成功");
        } catch (Exception e) {
            log.error("批量删除模板出错", e);
        }
        return Results.newFailResult(ErrorCode.SYSTEM_ERROR, "删除失败");
    }

    @Override
    public void exportModelToXml(String id, HttpServletResponse response) {
        try {
            Model modelData = repositoryService.getModel(id);
            BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
            JsonNode editorNode = new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
            BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);
            BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
            byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);
            ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
            IOUtils.copy(in, response.getOutputStream());
            String filename = bpmnModel.getMainProcess().getId() + ".bpmn20.xml";
            response.setHeader("Content-Disposition", "attachment; filename=" + filename);
            response.flushBuffer();
        } catch (Exception e) {
            throw new ActivitiException("导出model的xml文件失败，模型ID=" + id, e);
        }
    }

    @Override
    public void toEditPage(String id, HttpServletResponse response) {
        try {
            response.sendRedirect(String.format("%s/modeler?modelId=%s", UrlConsts.WORK_FLOW_CODE, id));
        } catch (IOException e) {
            log.error("跳转到编辑页出错", e);
        }
    }
}
